﻿//using Common.Framework.Extensions;
//using System;
//using System.Buffers.Text;
//using System.Buffers;
//using System.Collections.Concurrent;
//using System.Runtime.CompilerServices;
//using System.Text.Json;
//using System.Text.Json.Serialization;
//using System.Text;

//namespace Common.Framework.Serialize
//{
//    #region DateOnly & TimeOnly
//    /// <summary>
//    /// 专为 .net6 提供
//    /// </summary>
//    internal sealed class JsonConverterDateOnly : JsonConverter<DateOnly>
//    {
//        public string Format { get; set; }
//        public JsonConverterDateOnly()
//        {
//            this.Format = "yyyy-MM-dd";
//        }
//        public JsonConverterDateOnly(string format)
//        {
//            Format = format ?? throw new ArgumentNullException(nameof(format));
//        }
//        public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            return DateOnly.Parse(reader.GetString());
//        }

//        public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
//        {
//            writer.WriteStringValue(value.ToString(Format));
//        }
//    }

//    /// <summary>
//    /// 专为 .net6 提供
//    /// </summary>
//    internal sealed class JsonConverterTimeOnly : JsonConverter<TimeOnly>
//    {
//        public string Format { get; set; }
//        public JsonConverterTimeOnly()
//        {
//            this.Format = "HH:mm:ss.fffffff";
//        }
//        public JsonConverterTimeOnly(string format)
//        {
//            Format = format ?? throw new ArgumentNullException(nameof(format));
//        }
//        public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            return TimeOnly.Parse(reader.GetString());
//        }

//        public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options)
//        {
//            writer.WriteStringValue(value.ToString(Format));

//        }
//    }
//    #endregion

//    #region Datetime & DateTimeOffset
//    /// <summary>
//    /// DateTime转换器
//    /// </summary>
//    internal class JsonConverterDatetime : JsonConverter<DateTime>
//    {
//        /// <summary>
//        /// 如: "yyyy-MM-dd HH:mm:ss",默认: null
//        /// </summary>
//        public string Format { get; set; }
//        /// <summary>
//        /// 使用默认格式,同: <c>System.Text.Json.JsonSerializer.Serialize(obj)</c>
//        /// </summary>
//        public JsonConverterDatetime() { }
//        /// <summary>
//        /// 指定格式化字符串
//        /// </summary>
//        public JsonConverterDatetime(string format)
//        {
//            Format = format;
//        }
//        /// <summary>
//        /// 自定义反序列化方法
//        /// </summary>
//        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            if (!reader.TryGetDateTime(out DateTime value))
//            {
//                value = DateTime.Parse(reader.GetString()!);
//            }
//            return value;
//        }

//        /// <summary>
//        /// 自定义序列化方法
//        /// </summary>
//        public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
//        {
//            if (Format.IsNotNullOrEmptyOrWhiteSpace())
//            {
//                writer.WriteStringValue(value.ToString(Format));
//            }
//            else
//            {
//                Span<byte> utf8Date = new byte[50];
//                bool result = Utf8Formatter.TryFormat(value, utf8Date, out int len, new StandardFormat('O'));
//                if (result) writer.WriteStringValue(utf8Date.Slice(0, len));
//                else writer.WriteStringValue(value.ToString(Format));
//            }
//        }
//    }

//    /// <summary>
//    /// DateTimeOffset转换器
//    /// </summary>
//    internal class JsonConverterDateTimeOffset : JsonConverter<DateTimeOffset>
//    {
//        /// <summary>
//        /// 如: "yyyy-MM-dd HH:mm:ss",默认: null
//        /// </summary>
//        public string Format { get; set; }
//        /// <summary>
//        /// 使用默认格式,同: <c>System.Text.Json.JsonSerializer.Serialize(obj)</c>
//        /// </summary>
//        public JsonConverterDateTimeOffset() { }
//        /// <summary>
//        /// 指定格式化字符串
//        /// </summary>
//        /// <param name="format"></param>
//        public JsonConverterDateTimeOffset(string format)
//        {
//            Format = format;
//        }
//        /// <summary>
//        /// 自定义反序列化方法
//        /// </summary>
//        public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            if (!reader.TryGetDateTimeOffset(out DateTimeOffset value))
//            {
//                value = DateTimeOffset.Parse(reader.GetString()!);
//            }
//            return value;
//        }

//        /// <summary>
//        /// 自定义序列化方法
//        /// </summary>
//        public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
//        {
//            if (Format.IsNotNullOrEmptyOrWhiteSpace())
//            {
//                writer.WriteStringValue(value.ToString(Format));
//            }
//            else
//            {
//                Span<byte> utf8Date = new byte[50];
//                bool result = Utf8Formatter.TryFormat(value, utf8Date, out int len, new StandardFormat('O'));
//                if (result) writer.WriteStringValue(utf8Date.Slice(0, len));
//                else writer.WriteStringValue(value.ToString(Format));
//            }
//        }
//    }
//    #endregion

//    /// <summary>
//    /// string转换器,解决问题: <br />
//    /// 123 => "123"<br/>
//    /// true => "true"
//    /// </summary>
//    internal class JsonConverterString : JsonConverter<string>
//    {
//        /// <summary>
//        /// 空参构造函数
//        /// </summary>
//        public JsonConverterString() { }
//        /// <summary>
//        /// 自定义反序列化方法
//        /// </summary>
//        public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            switch (reader.TokenType)
//            {
//                case JsonTokenType.None:
//                case JsonTokenType.Null:
//                    return null;
//                case JsonTokenType.Number:
//                    return reader.GetDouble().ToString();
//                case JsonTokenType.True:
//                    return "true";
//                case JsonTokenType.False:
//                    return "false";
//                default:
//                    return reader.GetString();
//            }
//        }

//        /// <summary>
//        /// 自定义序列化方法
//        /// </summary>
//        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
//        {
//            writer.WriteStringValue(value);
//        }
//    }

//    internal class JsonConverterBool : JsonConverter<bool>
//    {
//        public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            switch (reader.TokenType)
//            {
//                case JsonTokenType.None:
//                case JsonTokenType.Null:
//                    throw new Exception($"无法将 null 反序列化为 bool!");
//                case JsonTokenType.Number:
//                    var d = reader.GetDouble();
//                    return !(d == 0);
//                case JsonTokenType.String:
//                    var str = reader.GetString();
//                    if (string.Equals(str, "true", StringComparison.OrdinalIgnoreCase)) return true;
//                    else if (string.Equals(str, "false", StringComparison.OrdinalIgnoreCase)) return false;
//                    else throw new Exception($"无法将非 \"true\"或\"false\" 的字符串 转为 bool!");
//                case JsonTokenType.True: return true;
//                case JsonTokenType.False: return false;
//                default: throw new Exception($"无法将 {reader.TokenType} 反序列化为 bool!");
//            }
//        }

//        public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
//        {
//            writer.WriteBooleanValue(value);
//        }
//    }
//    internal class NullAbleConverter : JsonConverterFactory
//    {
//        private static ConcurrentDictionary<Type, JsonConverter> _cache = new();
//        public override bool CanConvert(Type typeToConvert)
//        {
//            return typeToConvert.IsNullable();
//        }

//        public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
//        {
//            return _cache.GetOrAdd(typeToConvert, () =>
//            {
//                return (JsonConverter)Activator.CreateInstance(typeof(NullAbleConverter<>).MakeGenericType(typeToConvert));
//            });
//        }
//    }

//    internal class NullAbleConverter<T> : JsonConverter<T>
//    {
//        public NullAbleConverter()
//        {
//            s_UnderlyingType = Nullable.GetUnderlyingType(typeof(T));
//        }
//        private Type s_UnderlyingType = null;
//        public override bool CanConvert(Type typeToConvert)
//        {
//            return typeToConvert.IsNullable();
//        }
//        public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            switch (reader.TokenType)
//            {
//                case JsonTokenType.Null:
//                case JsonTokenType.None:
//                    return default;
//                case JsonTokenType.String:
//                    var str = reader.GetString();
//                    if (str.IsNullOrEmptyOrWhiteSpace()) return default;
//                    return (T)JsonSerializer.Deserialize(ref reader, s_UnderlyingType, options);
//                case JsonTokenType.StartArray:
//                    {
//                        if (s_UnderlyingType.IsEnum)
//                        {
//                            //将 [] 转为 EnumFlag? 的时候转为 null
//                            return (T)JsonEnumConverter.ConvertFromReaderWhenArray(ref reader, s_UnderlyingType, typeToConvert);
//                        }
//                        return (T)JsonSerializer.Deserialize(ref reader, s_UnderlyingType, options);
//                    }
//                default:
//                    return (T)JsonSerializer.Deserialize(ref reader, s_UnderlyingType, options);
//            }
//        }

//        public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
//        {
//            if (value == null)
//            {
//                writer.WriteStringValue("null");
//            }
//            else
//            {
//                JsonSerializer.Serialize(writer, value, value.GetType(), options);
//            }
//        }
//    }

//    internal class JsonEnumConverter : JsonConverterFactory
//    {
//        internal static object ConvertFromReaderWhenArray(ref Utf8JsonReader reader, Type typeToConvert, Type oldType)
//        {
//            var sb = new StringBuilder();
//            sb.Append('[');
//            var idx = 0;
//            while (reader.Read())
//            {
//                if (reader.TokenType == JsonTokenType.EndArray)
//                {
//                    sb.Append(']');
//                    break;
//                }
//                else if (reader.TokenType == JsonTokenType.String)
//                {
//                    idx++;
//                    if (idx > 1) sb.Append(',');
//                    sb.Append('"').Append(reader.GetString()).Append('"');
//                }
//                else if (reader.TokenType == JsonTokenType.Number)
//                {
//                    idx++;
//                    if (idx > 1) sb.Append(',');
//                    sb.Append(reader.GetInt32());
//                }
//                else throw new Exception($"无法将数组转成枚举({typeToConvert.GetClassFullName()}),除非是简单数组(如:[1,2],[\"close\",\"open\"])!");
//            }
//            return ObjectExtensions.ConvertToEnum(typeToConvert, oldType, sb.ToString());
//        }
//        public JsonEnumConverter(bool enum2String)
//        {
//            this.enum2String = enum2String;
//        }
//        private static ConcurrentDictionary<Type, JsonConverter> _cache2String = new ConcurrentDictionary<Type, JsonConverter>();
//        private static ConcurrentDictionary<Type, JsonConverter> _cache2Numer = new ConcurrentDictionary<Type, JsonConverter>();
//        private readonly bool enum2String;

//        public sealed override bool CanConvert(Type typeToConvert)
//        {
//            return typeToConvert.IsEnum;
//        }

//        public sealed override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
//        {
//            var _cache = enum2String ? _cache2String : _cache2Numer;
//            return _cache.GetOrAdd(typeToConvert, () =>
//            {
//                var ctor = typeof(EnumConverter<>).MakeGenericType(typeToConvert).GetConstructor(new Type[] { typeof(bool) });
//                return (JsonConverter)ctor.Invoke(new object[] { enum2String });
//            });
//        }
//    }

//    internal sealed class EnumConverter<T> : JsonConverter<T> where T : struct, Enum
//    {
//        public EnumConverter(bool enum2String)
//        {
//            this.enum2String = enum2String;
//        }
//        private static readonly TypeCode s_enumTypeCode = Type.GetTypeCode(typeof(T));
//        private readonly bool enum2String;

//        public override bool CanConvert(Type type)
//        {
//            return type.IsEnum;
//        }

//        public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            switch (reader.TokenType)
//            {
//                case JsonTokenType.String:
//                    {
//                        var str = reader.GetString();
//                        if (Enum.TryParse(typeof(T), str, true, out var ret)) return (T)ret;
//                        return (T)ObjectExtensions.ConvertToEnum(typeToConvert, typeToConvert, str);
//                    }
//                case JsonTokenType.Number:
//                    {
//                        switch (s_enumTypeCode)
//                        {
//                            case TypeCode.Int32:
//                                {
//                                    if (reader.TryGetInt32(out var value8))
//                                    {
//                                        return Unsafe.As<int, T>(ref value8);
//                                    }
//                                    break;
//                                }
//                            case TypeCode.UInt32:
//                                {
//                                    if (reader.TryGetUInt32(out var value4))
//                                    {
//                                        return Unsafe.As<uint, T>(ref value4);
//                                    }
//                                    break;
//                                }
//                            case TypeCode.UInt64:
//                                {
//                                    if (reader.TryGetUInt64(out var value6))
//                                    {
//                                        return Unsafe.As<ulong, T>(ref value6);
//                                    }
//                                    break;
//                                }
//                            case TypeCode.Int64:
//                                {
//                                    if (reader.TryGetInt64(out var value2))
//                                    {
//                                        return Unsafe.As<long, T>(ref value2);
//                                    }
//                                    break;
//                                }
//                            case TypeCode.SByte:
//                                {
//                                    if (reader.TryGetSByte(out var value7))
//                                    {
//                                        return Unsafe.As<sbyte, T>(ref value7);
//                                    }
//                                    break;
//                                }
//                            case TypeCode.Byte:
//                                {
//                                    if (reader.TryGetByte(out var value5))
//                                    {
//                                        return Unsafe.As<byte, T>(ref value5);
//                                    }
//                                    break;
//                                }
//                            case TypeCode.Int16:
//                                {
//                                    if (reader.TryGetInt16(out var value3))
//                                    {
//                                        return Unsafe.As<short, T>(ref value3);
//                                    }
//                                    break;
//                                }
//                            case TypeCode.UInt16:
//                                {
//                                    if (reader.TryGetUInt16(out var value))
//                                    {
//                                        return Unsafe.As<ushort, T>(ref value);
//                                    }
//                                    break;
//                                }
//                        }
//                        throw new Exception($"无法从 {JsonTokenType.Number} 转为枚举({typeToConvert.GetClassFullName()})!");
//                    }
//                case JsonTokenType.StartArray:
//                    return (T)JsonEnumConverter.ConvertFromReaderWhenArray(ref reader, typeToConvert, typeToConvert);
//                default:
//                    throw new Exception($"无法从 {reader.TokenType} 转为枚举({typeToConvert.GetClassFullName()})!");
//            }
//        }

//        public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
//        {
//            if (enum2String)
//            {
//                writer.WriteStringValue(value.ToString());
//            }
//            else
//            {
//                switch (s_enumTypeCode)
//                {
//                    case TypeCode.Int32:
//                        writer.WriteNumberValue(Unsafe.As<T, int>(ref value));
//                        break;
//                    case TypeCode.UInt32:
//                        writer.WriteNumberValue(Unsafe.As<T, uint>(ref value));
//                        break;
//                    case TypeCode.UInt64:
//                        writer.WriteNumberValue(Unsafe.As<T, ulong>(ref value));
//                        break;
//                    case TypeCode.Int64:
//                        writer.WriteNumberValue(Unsafe.As<T, long>(ref value));
//                        break;
//                    case TypeCode.Int16:
//                        writer.WriteNumberValue(Unsafe.As<T, short>(ref value));
//                        break;
//                    case TypeCode.UInt16:
//                        writer.WriteNumberValue(Unsafe.As<T, ushort>(ref value));
//                        break;
//                    case TypeCode.Byte:
//                        writer.WriteNumberValue(Unsafe.As<T, byte>(ref value));
//                        break;
//                    case TypeCode.SByte:
//                        writer.WriteNumberValue(Unsafe.As<T, sbyte>(ref value));
//                        break;
//                    default:
//                        throw new Exception($"无法将 {s_enumTypeCode} 序列化!");
//                }
//            }
//        }

//        public override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
//        {
//            switch (reader.TokenType)
//            {
//                case JsonTokenType.String:
//                    {
//                        var str = reader.GetString();
//                        if (Enum.TryParse(typeof(T), str, true, out var ret)) return (T)ret;
//                        return (T)ObjectExtensions.ConvertToEnum(typeToConvert, typeToConvert, str);
//                    }
//                case JsonTokenType.Number:
//                    switch (s_enumTypeCode)
//                    {
//                        case TypeCode.Int32:
//                            {
//                                if (reader.TryGetInt32(out var value8))
//                                {
//                                    return Unsafe.As<int, T>(ref value8);
//                                }
//                                break;
//                            }
//                        case TypeCode.UInt32:
//                            {
//                                if (reader.TryGetUInt32(out var value4))
//                                {
//                                    return Unsafe.As<uint, T>(ref value4);
//                                }
//                                break;
//                            }
//                        case TypeCode.UInt64:
//                            {
//                                if (reader.TryGetUInt64(out var value6))
//                                {
//                                    return Unsafe.As<ulong, T>(ref value6);
//                                }
//                                break;
//                            }
//                        case TypeCode.Int64:
//                            {
//                                if (reader.TryGetInt64(out var value2))
//                                {
//                                    return Unsafe.As<long, T>(ref value2);
//                                }
//                                break;
//                            }
//                        case TypeCode.SByte:
//                            {
//                                if (reader.TryGetSByte(out var value7))
//                                {
//                                    return Unsafe.As<sbyte, T>(ref value7);
//                                }
//                                break;
//                            }
//                        case TypeCode.Byte:
//                            {
//                                if (reader.TryGetByte(out var value5))
//                                {
//                                    return Unsafe.As<byte, T>(ref value5);
//                                }
//                                break;
//                            }
//                        case TypeCode.Int16:
//                            {
//                                if (reader.TryGetInt16(out var value3))
//                                {
//                                    return Unsafe.As<short, T>(ref value3);
//                                }
//                                break;
//                            }
//                        case TypeCode.UInt16:
//                            {
//                                if (reader.TryGetUInt16(out var value))
//                                {
//                                    return Unsafe.As<ushort, T>(ref value);
//                                }
//                                break;
//                            }
//                    }
//                    throw new Exception($"无法从 {JsonTokenType.Number} 转为枚举({typeToConvert.GetClassFullName()})!");
//                case JsonTokenType.PropertyName:
//                    {
//                        var str = reader.GetString();
//                        if (Enum.TryParse(typeof(T), str, true, out var ret)) return (T)ret;
//                        return (T)ObjectExtensions.ConvertToEnum(typeToConvert, typeToConvert, str);
//                    }
//                case JsonTokenType.StartArray:
//                    return (T)JsonEnumConverter.ConvertFromReaderWhenArray(ref reader, typeToConvert, typeToConvert);
//                default:
//                    throw new Exception($"无法从 {reader.TokenType} 转为枚举({typeToConvert.GetClassFullName()})!");
//            }
//        }

//        public override void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
//        {
//            writer.WritePropertyName(value.ToString());
//        }
//    }
//}
